package org.jetlinks.pro.assets.aop;

import org.jetlinks.pro.assets.annotation.AssetsController;
import org.jetlinks.pro.assets.annotation.MultiAssetsController;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.core.annotation.AnnotatedElementUtils;

import javax.annotation.Nonnull;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 使用静态方法匹配来进行AOP拦截,对注解了{@link AssetsController}的类、方法进行资产数据权限控制。
 * <p>
 * 控制逻辑见{@link AopAssetsControllerHandler}
 *
 * @author zhouhao
 * @see AopAssetsControllerHandler
 * @see AssetsController
 * @since 1.11
 */
public class AopAssetsControllerSupport extends StaticMethodMatcherPointcutAdvisor {

    private final static Set<String> ignoreMethod = Arrays
        .stream(Object.class.getMethods())
        .map(Method::getName)
        .collect(Collectors.toSet());

    @Override
    public boolean matches(@Nonnull Method method, @Nonnull Class<?> aClass) {
        //忽略hashCode,equals等方法
        if (ignoreMethod.contains(method.getName())) {
            return false;
        }
        //方法上的注解
        AssetsController mann = AnnotatedElementUtils.findMergedAnnotation(method, AssetsController.class);
        //类上的注解
        AssetsController cann = AnnotatedElementUtils.findMergedAnnotation(aClass, AssetsController.class);
        //方法上注解的多种资产控制
        MultiAssetsController multiAssets = AnnotatedElementUtils.findMergedAnnotation(method, MultiAssetsController.class);
        if (null != multiAssets) {
            return true;
        }
        if (mann != null) {
            return !mann.ignore();
        }
        if (cann != null) {
            return !cann.ignore();
        }
        return false;
    }
}
